<?php
/**
 * 游戏
 */
declare(strict_types=1);
/**
 * 游戏
 */

namespace App\Controller\slots;
use App\Controller\AbstractController;
use Hyperf\DbConnection\Db;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\RequestMapping;
use function Hyperf\Config\config;
use Hyperf\Di\Annotation\Inject;
use App\Common\Guzzle;
use App\Common\Common as ggCommon;
use  App\Common\Curl;
#[Controller(prefix:"huiduslots")]
class HuiduslotsController extends AbstractController{


    #[Inject]
    protected Common $common;
    #[Inject]
    protected Guzzle $guzzle;


    private array $zr_header = ["Content-Type" => "application/json"];


    private array $slots_type_correspond_terrace_id = ['t1' => 19,'evo' => 13,'ezugi' => 11,'spr' => 14];
    /**
     * 灰度结算
     * @return void
     */
    public function TransferInOut($param){

        $validator = $this->validatorFactory->make(
            $param,
            [
                'timestamp' => 'required',
                'payload' => 'required',

            ],
            [
                'timestamp.required' => 'timestamp is required',
                'payload.required' => 'payload is required',
            ]
        );


        if ($validator->fails()) {
            $errorMessage = $validator->errors()->first();
            $this->logger->error("HUIDU-TransferInOut验证账号接口数据验证失败===>".$errorMessage);
            return ['code' => 0,'msg' => '','payload' => $this->returnPayLoad()];
        }

        $payloadArray = $this->decryptArray($param['payload'],config('huiduslots.aes_key'));

//        $this->logger->error('huidu-payloadArray:'.json_encode($payloadArray));

        //效验货币是否正确
        if(config('huiduslots.currency') != $payloadArray['currency_code']){
            $this->logger->error('huidu-货币效验失败-currency_code:'.$payloadArray['currency_code']);
            return ['code' => 0,'msg' => '','payload' => $this->returnPayLoad()];
        }



        [$uid,$slots_type] = $this->getUidAndSlotsType($payloadArray['member_account']);

        $userinfo = $this->common->getUserInfo($uid);
        if(!$userinfo){
            $this->logger->error('huidu-数据库userinfo不存在用户-UID:'.$uid);
            return ['code' => 0,'msg' => '','payload' => $this->returnPayLoad()];
        }

        $credit_amount = bcadd((string)$userinfo['coin'],(string)$userinfo['bonus'],0);
        if($payloadArray['bet_amount'] < 0){//下注为负数理论上是要增加用户的余额,查看订单是否完成，完成了直接返回
            $res = $this->refundUserBettingAmount($uid,$payloadArray,$userinfo);
            if($res['code'] != 200) return ['code' => 0,'msg' => '','payload' => $this->returnPayLoad($credit_amount)];
            return ['code' => 0,'msg' => '','payload' => $this->returnPayLoad($res['data'])];
        }


        if(bcmul($payloadArray['bet_amount'],'100',0) > $credit_amount){
            $this->logger->error('huidu-下注金额大于了余额-bet_amount:'.$payloadArray['bet_amount']);
            return ['code' => 1,'msg' => '','payload' => $this->returnPayLoad()];
        }

        $slots_log = $this->common->SlotsLogView($payloadArray['game_round']);
        if($slots_log && !in_array($slots_log['is_settlement'],[0,4])){ //说明订单已经执行完了
            $this->logger->error('huidu-下注记录完成:'.$payloadArray['game_round']);
            return ['code' => 0,'msg' => '','payload' => $this->returnPayLoad($credit_amount)];
        }

        if(!$slots_log){
            //正式环境打开
            $res = $this->common->getUserRunGameTage($uid,$slots_type);
            if(!$res)['code' => 1,'msg' => '','payload' => $this->returnPayLoad()];

            $slots_game = Db::table('slots_game')->select('id','englishname')->where(['terrace_id' => $this->slots_type_correspond_terrace_id[$slots_type],'slotsgameid' => $payloadArray['game_uid']])->first();
            $slotsData = [
                'betId' => $payloadArray['game_round'],
                'parentBetId' => $payloadArray['game_round'],
                'uid' => $uid,
                'puid' => $userinfo['puid'],
                'slotsgameid' => $payloadArray['game_uid'],
                'englishname' => $slots_game['englishname'],
                'game_id' => $slots_game['id'],
                'terrace_name' => $slots_type,
                'transaction_id' => $payloadArray['serial_number'],
                'betTime' => time(),
                'channel' => $userinfo['channel'],
                'is_settlement' => 0,
                'package_id' => $userinfo['package_id'],
                'createtime' => time(),
            ];
            $res = $this->common->slotsLog($slotsData,$userinfo['coin'],$userinfo['bonus'],bcmul((string)$payloadArray['bet_amount'],'100',0),'0',2);
        }else{
            $res = $this->common->resultDealWith($slots_log,$userinfo,bcmul((string)$payloadArray['win_amount'],'100',0),2);
        }

        if($res['code'] != 200)return ['code' => 1,'msg' => '','payload' => $this->returnPayLoad()];
        return ['code' => 0,'msg' => '','payload' => $this->returnPayLoad($res['data'])];
    }


    /**
     * 退还用户下注金额
     * @param $uid
     * @param $payloadArray
     * @param $userinfo
     *
     */
    private function refundUserBettingAmount($uid,$payloadArray,$userinfo){
        $slots_log = $this->common->SlotsLogView($payloadArray['game_round']);
        if(!$slots_log || !in_array($slots_log['is_settlement'],[0,4])){ //说明订单已经执行完了
            $this->logger->error('huidu-下注记录不存在或者已完成:'.$payloadArray['game_round']);
            return ['code' => 201];
        }
        $user_bet_amount = bcadd((string)$slots_log['cashBetAmount'],(string)$slots_log['bonusBetAmount'],0);
        $huidu_bet_amount = bcmul(bcsub('0',(string)$payloadArray['bet_amount'],2),'100',0);
        if($user_bet_amount != $huidu_bet_amount){
            $this->logger->error('huidu-下注取消订单金额与单笔下注金额不一致-bet_amount:'.$huidu_bet_amount.'用户下注金额:'.$user_bet_amount);
            return ['code' => 201];
        }
        //给用户返回余额同时删除订单
        $this->common->userFundChange($uid,$slots_log['cashBetAmount'],$slots_log['bonusBetAmount'],bcadd((string)$userinfo['coin'],(string)$slots_log['cashBetAmount'],0),bcadd((string)$userinfo['bonus'],(string)$slots_log['bonusBetAmount'],0),$userinfo['channel'],$userinfo['package_id']);
        $this->common->deleteSlotsLog((string)$payloadArray['game_round']);
        return ['code' => 200,'data' => $slots_log['cashBetAmount'] + $slots_log['bonusBetAmount'] + $userinfo['coin'] + $userinfo['bonus']];
    }


    /**
     * 获取游戏启动url
     * @param $uid  玩家uid
     * @param $gameid  游戏的id
     * @param $slots_type  slots 厂商类型,用于追加到玩家ID后缀，区分是哪个三方游戏
     * @param $controllerRoute  控制器路由
     * @return array
     */
    public function getGameUrl($uid,$gameid,$slots_type,$controllerRoute){
        $url =  config('huiduslots.api_url').'/game/v1';
        $timestamp = time().rand(000,999);
        $body = [
            'agency_uid' => config('huiduslots.agency_uid'),
            'timestamp' => $timestamp,
            'payload' => $this->getPayload($gameid,$uid,$slots_type,$timestamp,$controllerRoute),
        ];

        $data = $this->guzzle->post($url,$body,$this->zr_header);
        // $this->logger->error('huidugetGameUrl:'.json_encode($data));
        if($data['code'] == 0){
            return ['code' => 200,'msg' => 'suc','data' => $data['payload']['game_launch_url']];
        }
        return ['code' => 201,'msg' => 'fail','data' => []];

    }

    /**
     * 获取下注的Payload 数据
     * @param $game_uid  三方游戏ID
     * @param $uid      玩家ID
     * @param $slots_type  游戏厂商缩写
     * @param $timestamp  时间戳
     * @param $controllerRoute  控制器路由
     * @return string
     */
    private function getPayload($game_uid,$uid,$slots_type,$timestamp,$controllerRoute){
        $res = $this->common->setUserMoney($uid);
        if($res['code'] != 200)$res['data'] = 0;


        $data = [
            'timestamp' => $timestamp,
            'agency_uid' => config('huiduslots.agency_uid'),
            'member_account' => config('huiduslots.player_prefix').$uid.'_'.$slots_type.config('huiduslots.player_suffix'),  //h6fd35_58711_t1_3377win 大概这个格式
            'game_uid' => $game_uid,
            'credit_amount' => bcdiv((string)$res['data'],'100',2),
            'currency_code' => config('huiduslots.currency'),
            'language' => config('huiduslots.language'),
            'platform' => 2, // 1-web（默认）、2-H5
            'callback_url' => config('host.apiDomain')."/$controllerRoute/TransferInOut",
        ];
        // $this->logger->error('$data:'.json_encode($data));
        return $this->encryptJson(json_encode($data),config('huiduslots.aes_key'));
    }


    /**
     * 返回下注的payload
     * @param $credit_amount  玩家余额
     * @return void
     */
    private function returnPayLoad($credit_amount = 0){
        $data = [
            'timestamp' => time().rand(000,999),
            'credit_amount' => bcdiv((string)$credit_amount,'100',2),
        ];

        return $this->encryptJson(json_encode($data),config('huiduslots.aes_key'));
    }

    /**
     * 获取uid和slots_type
     * @param $member_account  //h6fd35_58711_t1_3377win
     * @return array
     */
    private function getUidAndSlotsType($member_account){
        $uidPrefix = config('huiduslots.player_prefix');
        $uidArray = explode("_",$member_account);
        if($uidPrefix){ //有前缀就用中间的
            return [$uidArray[1],$uidArray[2]];
        }else{//没有前缀就用第一个
            return [$uidArray[0],$uidArray[1]];
        }
    }


    /**
     * 使用 AES-256 加密 JSON 字符串并返回 Base64 编码
     *
     * @param string $jsonString 要加密的 JSON 字符串
     * @param string $key 加密密钥 (必须是 32 字节)
     * @return string 加密后的 Base64 编码字符串
     */
    private  function encryptJson(string $jsonString, string $key): string {
        // 确保密钥长度为 32 字节 (256 位)
        if (strlen($key) !== 32) {
            return '0';
        }


        // 使用 AES-256-CBC 加密
        $encrypted = openssl_encrypt($jsonString, 'AES-256-ECB', $key, OPENSSL_RAW_DATA);

        // 并进行 Base64 编码
        return base64_encode($encrypted);


    }



    /**
     * 解密数据
     *
     * @param string $encryptString 加密之后的数据
     * @param string $key 加密密钥 (必须是 32 字节)
     * @return array
     */
    private function decryptArray(string $encryptString, string $key): array {
        // 确保密钥长度为 32 字节 (256 位)
        if (strlen($key) !== 32) {
            return '0';
        }


        // 使用 AES-256-CBC 加密
        $decrypt = openssl_decrypt(base64_decode($encryptString), 'AES-256-ECB', $key, OPENSSL_RAW_DATA);

        // 并进行 Base64 编码
        return json_decode($decrypt,true);


    }
}






